// 继承

// // 原型链继承
// function Animal() {
//     this.colors = ['black', 'white']
// }
// function Dog() {}
// Dog.prototype = new Animal()
// let dog1 = new Dog()
// let dog2 = new Dog()
// console.log(dog1.colors === dog2.colors)        // true
// // 原型链继承的缺点：
// // 1、原型中的引用数据类型属性被所有实例共享
// // 2、子类在实例化的时候不能给父类传递参数

// // 借用构造函数继承
// function Animal(name) {
//     this.name = name
//     this.colors = ['black', 'white']
//     this.getName = function() {
//         return this.name
//     }
// }
// function Dog(name) {
//     Animal.call(this, name)
// }
// Dog.prototype = new Animal()
// let dog1 = new Dog('小黑')
// let dog2 = new Dog('小发')
// dog1.colors.push('brown')
// console.log(dog1, dog2)
// // 解决了传参问题
// // 解决了引用数据类型实例间共享的问题，但是function也会被重新创建。


// // 组合继承
// function Animal(name) {
//     this.name = name
//     this.colors = ['black', 'white']
// }
// Animal.prototype.getName = function() {
//     return this.name
// }
// function Dog(name, age) {
//     Animal.call(this, name)
//     this.age = age
// }
// Dog.prototype = new Animal()
// Dog.prototype.constructor = Dog
// let dog1 = new Dog('小发', 1)
// let dog2 = new Dog('六六', 1)
// dog1.colors.push('brown')
// console.log(dog1.colors === dog2.colors)    // false
// console.log(dog1.getName === dog2.getName)  // true
// // 既解决了引用类型实例间共享的问题，又能让function共用。

// // 寄生式组合继承
// // 组合继承已经很完善了，但是还存在一个问题就是父类构造函数执行了两次，一次是Dog.prototype = new Animal()，另一次是Animal.call(this, name)
// // 解决方案就是不直接调用父类构造函数给子类原型复制，而是通过创建空函数获取父类原型的副本
// function Animal(name) {
//     console.log('父类构造函数执行')
//     this.name = name
//     this.colors = ['black', 'white']
// }
// Animal.prototype.getName = function() {
//     return this.name
// }
// function Dog(name, age) {
//     Animal.call(this, name)
//     this.age = age
// }
// function F() {}  // 创建空函数
// F.prototype = Animal.prototype  // 空函数prototype指向父类构造函数的prototype
// let prototype = new F() // 创建prototype副本
// prototype.constructor = Dog // 构造函数指向Dog
// Dog.prototype = prototype   // 修改Dog的prototype
// let dog1 = new Dog('六六', 1)
// // 父类构造函数只在子类构造函数进行实例化的时候执行一次

// // 上面继承式组合继承封装
// function getObj(o) {
//     function F() {}
//     F.prototype = o
//     return new F()
// }
// function inherit(child, parent) {
//     let prototype = getObj(parent.prototype)
//     prototype.constructor = child
//     child.prototype = prototype
// }
// // 食用方法：inherit(Dog, Animal)
// // 或者改为最简单的写法，将组合是继承Dog.prototype = new Animal()改为Dog.prototype = Object.create(Animal.prototype)

// ES6继承
class Animal {
    constructor(name) {
        this.name = name
        this.colors = ['black']
    }
    getName() {
        return this.name
    }
}
class Dog extends Animal {
    constructor(name, age) {
        super(name)
        this.age = age
    }
}
let dog1 = new Dog('小发', 18)
let dog2 = new Dog('六六', 1)
console.log(dog1.colors === dog2.colors)
console.log(dog1.getName === dog2.getName)